import { defineComponent, ref, inject, computed, watch, provide, createVNode } from 'vue';
import { FormContextKey } from '../Form/index.js';
import Popover from '../Popover/index.js';
import AsyncValidator from 'async-validator';

const FormItemContextKey = Symbol('FormItemContextKey');
const index = /* @__PURE__ */ defineComponent({
  name: 'FormItem',
  props: {
    inline: {
      type: Boolean,
      default: undefined
    },
    name: {
      type: String
    },
    labelStyle: {
      type: Object
    },
    label: {
      type: String
    },
    labelAlign: {
      type: String
    },
    rules: {
      type: Object
    },
    errorTransfer: {
      type: Boolean,
      default: undefined
    },
    errorAlign: {
      type: String,
      default: undefined
    }
  },
  setup(props, {
    slots
  }) {
    const error = ref(null);
    const ctx = inject(FormContextKey, null);
    let itemRef;
    const labelAlign = computed(() => props.labelAlign ?? 'center');
    const errorTransfer = props.errorTransfer ?? ctx?.errorTransfer ?? false;
    const errorAlign = props.errorAlign ?? ctx?.errorAlign ?? 'right';
    const name = props.name;
    const rules = ref([]);
    const isRequired = ref(false);
    watch(() => [ctx?.rules.value, props.rules], ([crules, prules]) => {
      const rs = crules ?? {};
      if (props.name) {
        rules.value = rs[props.name] ?? [];
      }
      if (prules) {
        rules.value = rules.value.concat(prules);
      }
      isRequired.value = rules.value.some(rule => rule.required);
    }, {
      immediate: true
    });
    const clazzName = computed(() => ({
      'cm-form-item': true,
      'cm-form-item-error': error.value,
      'cm-form-item-inline': props.inline || ctx?.inline,
      'cm-form-item-required': isRequired.value && props.label
    }));
    const check = async v => {
      if (itemRef) {
        const rect = itemRef.getBoundingClientRect();
        if (rect.width === 0 || rect.height === 0) {
          return true;
        }
      }
      if (name && rules.value.length) {
        const descriptor = {
          [`${name}`]: rules.value
        };
        const validator = new AsyncValidator(descriptor);
        const model = {
          [`${name}`]: v
        };
        return new Promise(resolve => {
          validator.validate(model, {
            firstFields: true
          }, errors => {
            if (errors) {
              error.value = errors[0].message;
              resolve(false);
            } else {
              error.value = null;
              resolve(true);
            }
          });
        });
      }
      return true;
    };
    if (!props.name) {
      console.warn('formItem needs name property to check valid');
    }
    const clearError = () => {
      error.value = null;
    };
    props.name && ctx?.setCheck && ctx.setCheck(props.name, check);
    props.name && ctx?.setClearValid && ctx.setClearValid(props.name, clearError);
    provide(FormItemContextKey, {
      name: props.name
    });
    return () => createVNode("div", {
      "class": clazzName.value
    }, [createVNode("label", {
      "class": {
        "cm-form-label": true,
        [`cm-form-label-${labelAlign.value}`]: true
      },
      "style": {
        width: ctx?.labelWidth + 'px',
        ...props.labelStyle
      }
    }, [props.label]), errorTransfer ? createVNode(Popover, {
      "class": "cm-form-item-error-popover",
      "arrow": true,
      "align": errorAlign,
      "theme": "error",
      "disabled": !error.value,
      "content": error.value
    }, {
      default: () => [createVNode("div", {
        "class": "cm-form-item-element",
        "ref": el => itemRef = el
      }, [slots.default?.()])]
    }) : createVNode("div", {
      "class": "cm-form-item-element",
      "ref": el => itemRef = el
    }, [slots.default?.(), createVNode("div", {
      "class": "cm-form-item-error-tip"
    }, [error.value])])]);
  }
});

export { FormItemContextKey, index as default };
